package wtflog

import (
	"runtime"
	"strconv"
	"time"

	. "gitee.com/FlyingOnion/wtflog/types"
)

type Field interface {
	// ApplyTo returns the raw value of field.
	ApplyTo(Event) string
	Key() string
}

type TextLoggerField interface {
	Field
	Prefix() string
	Suffix() string
}

type fieldCaller struct{}

func (fieldCaller) Key() string { return "caller" }

func (fieldCaller) ApplyTo(e Event) string {
	_, file, line, ok := runtime.Caller(e.CallerSkip)
	if !ok {
		return "unknown"
	}
	return file + ":" + Int(line).String()
}

func (fieldCaller) Prefix() string { return "caller=" }

func (fieldCaller) Suffix() string { return "" }

type fieldLevel struct{}

func (fieldLevel) Key() string { return "level" }

func (fieldLevel) ApplyTo(e Event) string {
	if s, ok := LevelMap[e.Level]; ok {
		return s
	}
	return LevelMap[LevelUnknown]
}

func (fieldLevel) Prefix() string { return "level=" }

func (fieldLevel) Suffix() string { return "" }

const (
	defaultTimeFormat = "2006-01-02 15:04:05"
)

type fieldTime struct{}

func (fieldTime) Key() string { return "time" }

func (fieldTime) ApplyTo(e Event) string { return e.Time.Format(defaultTimeFormat) }

func (fieldTime) Prefix() string { return "time=" }

func (fieldTime) Suffix() string { return "" }

type TimeFormatFunc func(t time.Time) string

func (TimeFormatFunc) Key() string { return "time" }

func (fn TimeFormatFunc) ApplyTo(e Event) string { return fn(e.Time) }

func (fn TimeFormatFunc) Prefix() string { return "time=" }

func (fn TimeFormatFunc) Suffix() string { return "" }

var (
	// FieldCaller adds a caller field.
	// To set caller skip level, use WithCallerSkip.
	FieldCaller fieldCaller
	FieldLevel  fieldLevel
	FieldTime   fieldTime

	FieldTimestamp TimeFormatFunc = func(t time.Time) string {
		return strconv.FormatInt(t.Unix(), 10)
	}

	FieldTimestampNano TimeFormatFunc = func(t time.Time) string {
		return strconv.FormatInt(t.UnixNano(), 10)
	}
)
